<?php

namespace Kanin\Games\model;

use Kanin\Games\gameInit;
use Kanin\Games\lib\Config;
use Kanin\Games\lib\Pool;
use Kanin\Games\lib\Tool;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;


class User extends BaseModel {

	const TABLE_NAME = "games.users";
	const JWT_KEY = "Au6YiKKkNf83vT8f";

	/**
	 * 添加经验值
	 */
	public function addExp($uid): array {
		$user = self::find($uid);
		$level = $user->level ?? 1;
		$config = Config::get('level', 'level');
		$key = 'user:exp:' . $uid;
		$addExp = $config[$level]['inc'];
		$redis = Pool::$redis->get();
		$exp = $redis->incrBy($key, $addExp);
		Pool::$redis->put($redis);
		return ['addExp' => $addExp, 'exp' => $exp];
	}

	/**
	 * 获取经验
	 * @param $uid
	 * @return false|mixed|\Redis|string
	 * @throws \RedisException
	 */
	public function userExp($uid) {
		$key = 'user:exp:' . $uid;
		$redis = Pool::$redis->get();
		$exp = $redis->get($key);
		Pool::$redis->put($redis);
		return $exp;
	}

	/**
	 * 创建
	 * @param $username
	 * @param $password
	 * @return \MongoDB\Driver\WriteResult
	 * @throws \Kanin\MyTools\Exception\KMongoException
	 */
	public function create($username, $password): \MongoDB\Driver\WriteResult {
		$id = Tool::model('tableIds')->makeId('users');
		$user = [
			'_id' => $id,
			'uid' => $id,
			'username' => $username,
			'password' => password_hash($password, PASSWORD_DEFAULT)
		];
		$mongo = Pool::$mongo->get();
		$data = $mongo->collection(self::TABLE_NAME)->insert($user);
		Pool::$mongo->put($mongo);
		return $data;
	}

	/**
	 * 查询用户
	 * @param $id
	 * @return array|mixed
	 * @throws \Kanin\MyTools\Exception\KMongoException
	 * @throws \MongoDB\Driver\Exception\Exception
	 */
	public function find($id) {
		$mongo = Pool::$mongo->get();
		$data = $mongo->collection(self::TABLE_NAME)->filter(['_id' => $id])->getOne();
		Pool::$mongo->put($mongo);
		return $data;
	}

	/**
	 * 查询用户
	 * @return array|mixed
	 * @throws \Kanin\MyTools\Exception\KMongoException
	 * @throws \MongoDB\Driver\Exception\Exception
	 */
	public function getOne($filter) {
		$mongo = Pool::$mongo->get();
		$data = $mongo->collection(self::TABLE_NAME)->filter($filter)->getOne();
		Pool::$mongo->put($mongo);
		return $data;
	}

	/**
	 * 查询用户
	 * @return array|mixed
	 * @throws \Kanin\MyTools\Exception\KMongoException
	 * @throws \MongoDB\Driver\Exception\Exception
	 */
	public function findByUsername($username) {
		$mongo = Pool::$mongo->get();
		$data = $mongo->collection(self::TABLE_NAME)->where('username', '=', $username)->getOne();
		Pool::$mongo->put($mongo);
		return $data;
	}

	/**
	 * 更新用户
	 * @param $data
	 * @param $uid
	 * @return false|\MongoDB\Driver\WriteResult
	 * @throws \Kanin\MyTools\Exception\KMongoException
	 */
	public function update($data, $uid) {
		$mongo = Pool::$mongo->get();
		$data = $mongo->collection(self::TABLE_NAME)
			->where('uid', '=', $uid)
			->update(['$set'=>$data], ['upsert' => false]);
		Pool::$mongo->put($mongo);
		return $data;
	}

	/**
	 * 生成token
	 *
	 * 字段说明：
	 * iss: jwt签发者
	 * sub: jwt所面向的用户
	 * aud: 接收jwt的一方
	 * exp: jwt的过期时间，这个过期时间必须要大于签发时间
	 * nbf: 定义在什么时间之前，该jwt都是不可用的.
	 * iat: jwt的签发时间
	 * jti: jwt的唯一身份标识，主要用来作为一次性token,从而回避重放攻击。
	 *
	 * https://github.com/firebase/php-jwt
	 * @param $uid
	 * @return string
	 */
	public function makeToken($uid): string {
		$payload = [
//			'iss' => 'http://example.org',
//			'aud' => 'http://example.com',
			'iat' => time(),
			'nbf' => time(),
			'uid' => $uid
		];

		/**
		 * IMPORTANT:
		 * You must specify supported algorithms for your application. See
		 * https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40
		 * for a list of spec-compliant algorithms.
		 */
		return JWT::encode($payload, self::JWT_KEY, 'HS256');
	}

	public function decodeToken($token): array {
		$decoded = [];
		try {
			$decoded = JWT::decode($token, new Key(self::JWT_KEY, 'HS256'));
		} catch (\UnexpectedValueException|\Throwable $exception) {
			//Logs::init()->exLogWrite($exception->getCode(), $exception->getMessage(), $exception->getTraceAsString());
		}
		return (array)$decoded;
	}
}